using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Runtime.InteropServices;

public static class AlexMath
{
    const double reversedRoot2Pi = 0.39894228040143267793994605993438;
    [DllImport("AlexMathExt")]
    public static extern double Phi(double x);
    public static double phi(double x)
    {
        return System.Math.Exp(-0.5 * x * x) * reversedRoot2Pi;
    }
    public static double theta(double x1,double x2)
    {
        return System.Math.Sqrt(x1 * x1 + x2 * x2);
    }
    public static void Cal_MeanAndVariance1(int thisIndex, int lastIndex, double[] mean, double[] variance, bool[] is_sum)
    {
        Cal_Mean1(thisIndex, lastIndex, mean, variance, is_sum);
        Cal_Variance1(thisIndex, lastIndex, mean, variance, is_sum);
        if (!is_sum[thisIndex])
        {
            is_sum[thisIndex] = true;
        }
    }
    public static void Cal_MeanAndVariance2(int thisIndex, int lastIndex, double[] mean, double[] variance, bool[] is_sum)
    {
        Cal_Mean2(thisIndex, lastIndex, mean, variance, is_sum);
        Cal_Variance2(thisIndex, lastIndex, mean, variance, is_sum);
        if (!is_sum[thisIndex])
        {
            is_sum[thisIndex] = true;
        }
    }
    private static void Cal_Mean1(int thisIndex,int lastIndex,double[] mean,double[] variance,bool[] is_sum)
    {
        if (!is_sum[thisIndex])
        {
            mean[thisIndex] += mean[lastIndex];
        }
        else
        {
            double delta = mean[thisIndex] - mean[lastIndex];
            double divDelta = delta / theta(variance[thisIndex], variance[lastIndex]);
            mean[thisIndex] =
                mean[thisIndex] * Phi(divDelta) + mean[lastIndex] * Phi(-divDelta) + 
                theta(variance[thisIndex], variance[lastIndex]) * phi(divDelta);
        }
    }
    private static void Cal_Mean2(int thisIndex, int lastIndex, double[] mean, double[] variance, bool[] is_sum)
    {
        if (!is_sum[thisIndex])
        {
            mean[thisIndex] += mean[lastIndex];
        }
        else
        {
            double delta = mean[thisIndex] - mean[lastIndex];
            double divDelta = delta / theta(variance[thisIndex], variance[lastIndex]);
            mean[thisIndex] =
                mean[thisIndex] * Phi(-divDelta) + mean[lastIndex] * Phi(divDelta) -
                theta(variance[thisIndex], variance[lastIndex]) * phi(-divDelta);
        }
    }
    private static void Cal_Variance1(int thisIndex, int lastIndex, double[] mean, double[] variance, bool[] is_sum)
    {
        if (!is_sum[thisIndex])
        {
            variance[thisIndex] = theta(variance[thisIndex], variance[lastIndex]);
        }
        else
        {
            double delta = mean[thisIndex] - mean[lastIndex];
            double divDelta = delta / theta(variance[thisIndex], variance[lastIndex]);
            double meanSquareX =
                (mean[thisIndex] * mean[thisIndex] + variance[thisIndex] * variance[thisIndex]) * Phi(divDelta) +
                (mean[lastIndex] * mean[lastIndex] + variance[lastIndex] * variance[lastIndex]) * Phi(-divDelta) +
                (mean[thisIndex] + mean[lastIndex]) * theta(mean[thisIndex], mean[lastIndex]) * phi(divDelta);
            variance[thisIndex] = meanSquareX - mean[thisIndex] * mean[thisIndex];
        }
    }
    private static void Cal_Variance2(int thisIndex, int lastIndex, double[] mean, double[] variance, bool[] is_sum)
    {
        if (!is_sum[thisIndex])
        {
            variance[thisIndex] = theta(variance[thisIndex], variance[lastIndex]);
        }
        else
        {
            double delta = mean[thisIndex] - mean[lastIndex];
            double divDelta = delta / theta(variance[thisIndex], variance[lastIndex]);
            double meanSquareX =
                (mean[thisIndex] * mean[thisIndex] + variance[thisIndex] * variance[thisIndex]) * Phi(-divDelta) +
                (mean[lastIndex] * mean[lastIndex] + variance[lastIndex] * variance[lastIndex]) * Phi(divDelta) -
                (mean[thisIndex] + mean[lastIndex]) * theta(mean[thisIndex], mean[lastIndex]) * phi(-divDelta);
            variance[thisIndex] = meanSquareX - mean[thisIndex] * mean[thisIndex];
        }
    }
}
